﻿using System;
using System.Linq;
using System.Web.Mvc;
using ControleRepresentante.Logic.Models;
using ControleRepresentante.Logic.Repositories;
using ControleRepresentante.Logic.Statistics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using WebSite.Controllers;
using Attribute = ControleRepresentante.Logic.Models.Attribute;

namespace ControleRepresentante.UnitTests.Controllers
{
    [TestClass]
    public class AttributeControllerTests : CRUDControllerTestScenarioBase<AttributeController, Attribute, IAttributeRepository, StatisticsBase>
    {
        private Representante m_Representante;
        private const string Name = "Attrib name";
        private const AttributeType Type = AttributeType.Vendedor;

        protected override AttributeController CreateController(bool isRepresentante = true)
        {
            this.LoginAsAdmin();
            Guid representanteId = this.CreateRepresentante("repre", true, "repreuser");
            Guid otherRepresentanteId = this.CreateRepresentante("otherrepre", false, "other");
            IRepresentanteRepository representanteRepository = RepositoryProvider.GetRepository<IRepresentanteRepository>();
            m_Representante = representanteRepository.GetModelById(representanteId);
            Representante otherRepresentante = representanteRepository.GetModelById(otherRepresentanteId);
            new Attribute { Name = "a" }.Representante = otherRepresentante;
            new Attribute { Name = "b" }.Representante = otherRepresentante;
            if (isRepresentante)
            {
                this.Logout();
                this.LoginAs("repreuser");
            }
            return new AttributeController(RepositoryProvider, SessionConfiguration, ControllerExtensionProvider);
        }

        protected override Attribute CreateModel()
        {
            return new Attribute {Name = Guid.NewGuid().ToString(), Representante = m_Representante};
        }

        protected override ActionResult Create(AttributeController controller)
        {
            return controller.Create(Name, Type.ToString());
        }

        protected override void VerifyModel(Attribute model)
        {
            Assert.AreEqual(Name, model.Name);
            Assert.AreEqual(Type, model.Type);
        }

        protected override ActionResult CreateEmptyFields(AttributeController controller)
        {
            return controller.Create(String.Empty, Type.ToString());
        }

        protected override void VerifyModelEmptyFields(Attribute model)
        {
            Assert.AreEqual(String.Empty, model.Name);
            Assert.AreEqual(Type, model.Type);
        }

        protected override ActionResult CreateDuplicatedModel(AttributeController controller, Attribute model)
        {
            return controller.Create(model.Name, Type.ToString());
        }

        protected override void VerifyDuplicatedModel(Attribute originalModel, Attribute duplicatedModel)
        {
            Assert.AreEqual(originalModel.Name, duplicatedModel.Name);
            Assert.AreEqual(originalModel.Type, duplicatedModel.Type);
        }

        protected override ActionResult Edit(AttributeController controller)
        {
            return controller.Edit(Name);
        }

        protected override ActionResult EditEmptyFields(AttributeController controller)
        {
            return controller.Edit(String.Empty);
        }

        protected override ActionResult EditDuplicatedModel(AttributeController controller, Attribute modelToDuplicate)
        {
            return controller.Edit(modelToDuplicate.Name);
        }

        [TestMethod]
        [ExpectedException(typeof(LoginException))]
        public void TestAttributesNotAtivoRepresentante()
        {
            CreateController(false);
            this.LoginAs("other");
        }

        [TestMethod]
        public void TestDeleteAttributeUsedByVendedor()
        {
            this.LoginAsAdmin();
            this.CreateRepresentante("my representante", true, "user");
            this.Logout();
            this.LoginAs("user");
            Guid attributeId = this.CreateAttribute(AttributeType.Vendedor, "my attribute");
            Vendedor vendedor = new Vendedor { Nome = "nome" };
            vendedor.AddAttributeValue(new AttributeValue
            {
                Attribute = new Attribute { Name = "my attribute" },
                Value = "value"
            });
            Guid vendedorId = this.CreateVendedor(vendedor);
            this.DeleteAttribute(attributeId);
            IVendedorRepository vendedorRepository = RepositoryProvider.GetRepository<IVendedorRepository>();
            vendedor = vendedorRepository.GetModelById(vendedorId);
            Assert.IsFalse(vendedor.AttributeValues.Any());
        }
        
        [TestMethod]
        public void TestDeleteAttributeUsedByFabrica()
        {
            this.LoginAsAdmin();
            this.CreateRepresentante("my representante", true, "user");
            this.Logout();
            this.LoginAs("user");
            Guid attributeId = this.CreateAttribute(AttributeType.Fabrica, "my attribute");
            Fabrica fabrica = new Fabrica { Nome = "nome", CNPJ = "cnpj", InscricaoEstadual = "inscricao"};
            fabrica.AddAttributeValue(new AttributeValue
            {
                Attribute = new Attribute { Name = "my attribute" },
                Value = "value"
            });
            Guid fabricaId = this.CreateFabrica(fabrica);
            this.DeleteAttribute(attributeId);
            IFabricaRepository fabricaRepository = RepositoryProvider.GetRepository<IFabricaRepository>();
            fabrica = fabricaRepository.GetModelById(fabricaId);
            Assert.IsFalse(fabrica.AttributeValues.Any());
        }        

        [TestMethod]
        public void TestDeleteAttributeUsedByTransportadora()
        {
            this.LoginAsAdmin();
            this.CreateRepresentante("my representante", true, "user");
            this.Logout();
            this.LoginAs("user");
            Guid attributeId = this.CreateAttribute(AttributeType.Transportadora, "my attribute");
            Transportadora transportadora = new Transportadora { Nome = "nome" };
            transportadora.AddAttributeValue(new AttributeValue
            {
                Attribute = new Attribute { Name = "my attribute" },
                Value = "value"
            });
            Guid transportadoraId = this.CreateTransportadora(transportadora);
            this.DeleteAttribute(attributeId);
            ITransportadoraRepository transportadoraRepository = RepositoryProvider.GetRepository<ITransportadoraRepository>();
            transportadora = transportadoraRepository.GetModelById(transportadoraId);
            Assert.IsFalse(transportadora.AttributeValues.Any());
        }

        [TestMethod]
        public void TestDeleteAttributeUsedByCliente()
        {
            this.LoginAsAdmin();
            this.CreateRepresentante("my representante", true, "user");
            this.Logout();
            this.LoginAs("user");
            Guid attributeId = this.CreateAttribute(AttributeType.Cliente, "my attribute");
            Guid vendedorId = this.CreateVendedor(new Vendedor{Nome ="vendedor"});
            Cliente cliente = new Cliente
            {
                RazaoSocial = "razao social",
                NomeFantasia = "nome fantasia",
                Vendedor = new Vendedor {Id = vendedorId},
            };
            cliente.AddAttributeValue(new AttributeValue
            {
                Attribute = new Attribute { Name = "my attribute" },
                Value = "value"
            });
            Guid clienteId = this.CreateCliente(cliente);
            this.DeleteAttribute(attributeId);
            IClienteRepository clienteRepository = RepositoryProvider.GetRepository<IClienteRepository>();
            cliente = clienteRepository.GetModelById(clienteId);
            Assert.IsFalse(cliente.AttributeValues.Any());
        }
    }
}
